package com.ocom.websocket.websocket;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.ocom.common.resp.Result;
import com.ocom.common.utils.DateUtil;
import com.ocom.common.utils.StringUtils;
import com.ocom.common.vo.recode.AccessRecordVo;
import com.ocom.common.vo.webapi.PageVO;
import com.ocom.common.vo.websocket.UserVo;
import com.ocom.websocket.feign.AccessClientService;
import com.ocom.websocket.feign.MjRecodeClientService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.tio.core.ChannelContext;
import org.tio.core.Tio;
import org.tio.core.TioConfig;
import org.tio.http.common.HttpRequest;
import org.tio.http.common.HttpResponse;
import org.tio.websocket.common.WsRequest;
import org.tio.websocket.common.WsResponse;
import org.tio.websocket.server.handler.IWsMsgHandler;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 消息处理类
 */
@Component
public class MyHandler implements IWsMsgHandler {

	private static Map<String, TioConfig> clients = new ConcurrentHashMap<String, TioConfig>();

	private Logger logger = LoggerFactory.getLogger(MyHandler.class);

	@Autowired
	private AccessClientService accessClientService;

	@Autowired
	private MjRecodeClientService mjRecodeClientService;


	/**
	 * <li>对httpResponse参数进行补充并返回，如果返回null表示不想和对方建立连接，框架会断开连接，如果返回非null，框架会把这个对象发送给对方</li>
	 * <li>注：请不要在这个方法中向对方发送任何消息，因为这个时候握手还没完成，发消息会导致协议交互失败。</li>
	 * <li>对于大部分业务，该方法只需要一行代码：return httpResponse;</li>
	 *
	 * @param httpRequest
	 * @param httpResponse
	 * @param channelContext
	 * @return
	 * @throws Exception
	 * @author tanyaowu
	 */
	@Override
	public HttpResponse handshake(HttpRequest httpRequest, HttpResponse httpResponse, ChannelContext channelContext) throws Exception {
		// 可以在此做一些业务逻辑，返回null表示不想连接
		return httpResponse;
	}

	/**
	 * 握手成功后触发该方法
	 *
	 * @param httpRequest
	 * @param httpResponse
	 * @param channelContext
	 * @throws Exception
	 * @author tanyaowu
	 */
	@Override
	public void onAfterHandshaked(HttpRequest httpRequest, HttpResponse httpResponse, ChannelContext channelContext) throws Exception {
		// 拿到用户id
		String id = httpRequest.getParam("id");

		clients.put(id,channelContext.getTioConfig());

		// 绑定用户
		Tio.bindUser(channelContext, id);
		// 给用户发送消息
		WsResponse wsResponse = WsResponse.fromText("如果您看到此消息，表示您已成功连接 WebSocket 服务器", "UTF-8");

		Tio.sendToUser(channelContext.tioConfig, id, wsResponse);
	}

	/**
	 * <li>当收到Opcode.BINARY消息时，执行该方法。也就是说如何你的ws是基于BINARY传输的，就会走到这个方法</li>
	 *
	 * @param wsRequest
	 * @param bytes
	 * @param channelContext
	 * @return 可以是WsResponse、byte[]、ByteBuffer、String或null，如果是null，框架不会回消息
	 * @throws Exception
	 * @author tanyaowu
	 */
	@Override
	public Object onBytes(WsRequest wsRequest, byte[] bytes, ChannelContext channelContext) throws Exception {
		return null;
	}


	/**
	 * 当收到Opcode.CLOSE时，执行该方法，业务层在该方法中一般不需要写什么逻辑，空着就好
	 *
	 * @param wsRequest
	 * @param bytes
	 * @param channelContext
	 * @return 可以是WsResponse、byte[]、ByteBuffer、String或null，如果是null，框架不会回消息
	 * @throws Exception
	 * @author tanyaowu
	 */
	@Override
	public Object onClose(WsRequest wsRequest, byte[] bytes, ChannelContext channelContext) throws Exception {
		// 关闭连接
		Tio.remove(channelContext, "WebSocket Close");
		return null;
	}

	/**
	 * <li>当收到Opcode.TEXT消息时，执行该方法。也就是说如何你的ws是基于TEXT传输的，就会走到这个方法</li>
	 *
	 * @param wsRequest
	 * @param text
	 * @param channelContext
	 * @return 可以是WsResponse、byte[]、ByteBuffer、String或null，如果是null，框架不会回消息
	 * @throws Exception
	 * @author tanyaowu
	 */
	@Override
	public Object onText(WsRequest wsRequest, String text, ChannelContext channelContext) throws Exception {
		WsResponse wsResponse = WsResponse.fromText("服务器已收到消息：" + text, "UTF-8");


		logger.info("websocket#  companyId:【{}】,收到消息:【{}】,",channelContext.userid,text);
		if(text.equals("heartbeat")){
			Tio.sendToUser(channelContext.tioConfig, channelContext.userid, wsResponse);
			return null;
		}

		try{
			Map<String,Object> map= JSON.parseObject(text,Map.class);
			Integer companyId= (Integer) map.get("companyId");
			Integer type= (Integer) map.get("type");
			System.out.println(companyId);
			System.out.println(type);
			//大屏统计
			Map<String,Object>  respMap=new HashMap<>();
			if(type==2 && companyId!=0){
//				Result result=accessClientService.LargeScreenGetYkmNums(companyId.longValue());
//				respMap.put("perSonNum",result.getData());
//				logger.info("websocket#大屏展示  接口:【{}】,返回:【{}】,","健康码人数",result);
//				Result result1=accessClientService.LargeScreenGetYkmSumByHS(companyId.longValue());
//				logger.info("websocket#大屏展示  接口:【{}】,返回:【{}】,","核酸检测归类统计",result1);
//				respMap.put("HsType",result1.getData());
//				Result result2=accessClientService.LargeScreenGetYkmSumByYM(companyId.longValue());
//				logger.info("websocket#大屏展示  接口:【{}】,返回:【{}】,","疫苗接种归类统计",result2);
//				respMap.put("YmType",result2.getData());
				JSONObject object = new JSONObject();
				object.put("comId",companyId);
				Result result2=accessClientService.getYkmPersonnelSum(object);
				respMap.put("data",result2.getData());
				Result result3=accessClientService.YkmInfo(companyId.longValue(),0l);
				logger.info("websocket#大屏展示  接口:【{}】,返回:【{}】,","标题",result3);
				respMap.put("title","关爱通健康码自动核验系统");
				try{
					if(result3.getCode()==200){
						Gson gson=new Gson();
						Map<String, Object> entityMjYkm =gson.fromJson(gson.toJson(result3.getData()),Map.class);
						respMap.put("title",entityMjYkm.get("title"));
					}
				}catch (Exception e){
					logger.info("websocket#获取粤康码规则#异常  接口:【{}】,返回:【{}】,","疫苗接种归类统计",e);
				}
				respMap.put("type",2);
				wsResponse = WsResponse.fromText(JSON.toJSONString(respMap),"UTF-8");
				Tio.sendToUser(channelContext.tioConfig, channelContext.userid, wsResponse);
				return null;
			}
			//大屏统计
			if(type==3 && companyId!=0){
				AccessRecordVo onShowVo=new AccessRecordVo();
				onShowVo.setAreaNo(0);
				onShowVo.setComId(companyId);
				onShowVo.setBeginTime(DateUtil.getDateTime(DateUtil.addDays(new Date(),-10)));
				onShowVo.setEndTime(DateUtil.getDateTime(new Date()));
				onShowVo.setPage(1);
				onShowVo.setSize(100);
				onShowVo.setYctRetcode("200");

				Result  mr = mjRecodeClientService.GetAccessRecord(onShowVo);
				List<UserVo> list=new ArrayList<>();
				Gson gson=new Gson();
				if(mr.getCode()==200){
					try {
//						PageVO result1 = gson.fromJson(gson.toJson(mr.getData()),PageVO.class);
						PageVO result1 =  JSON.parseObject(JSON.toJSONString(mr.getData()),PageVO.class) ;
						List<Object>  list1 = result1.getRecords();
						System.out.println(result1);
						System.out.println(list1);
						if(list1!=null && list1.size()>0){
							for (Object object:list1){
								Map<String, Object> stringObjectMap = gson.fromJson(gson.toJson(object),Map.class);
//								MjRecord mjRecord=gson.fromJson(gson.toJson(object),MjRecord.class);
								UserVo userVo=new UserVo();
								userVo.setPName(StringUtils.desValue((String) stringObjectMap.get("pname"),1,1,"*"));
								userVo.setCodeColor((String) stringObjectMap.get("codeColor"));
								userVo.setOpenTime((String) stringObjectMap.get("openTime"));
								list.add(userVo);
							}
						}
					}catch (Exception e){
						logger.info("websocket#记录列表  异常:【{}】",e);
					}
				}
				respMap.put("data",list);
				respMap.put("type",3);
				wsResponse = WsResponse.fromText(JSON.toJSONString(respMap),"UTF-8");
				Tio.sendToUser(channelContext.tioConfig, channelContext.userid, wsResponse);
				return null;
			}else if (type==4 && companyId!=0){
				Result getStudentSumBySchool=accessClientService.getNH(Long.valueOf(String.valueOf(companyId)));
				if (getStudentSumBySchool.getCode()==200){
					respMap.put("data",getStudentSumBySchool.getData());
					respMap.put("type",4);
					wsResponse = WsResponse.fromText(JSON.toJSONString(respMap),"UTF-8");
					Tio.sendToUser(channelContext.tioConfig, channelContext.userid, wsResponse);
					return null;
				}else {
					logger.info("websocket#大屏展示(学生在校人数统计) 请求失败 请求返回:【{}】",getStudentSumBySchool);
					return null;
				}
			}
		}catch (Exception e){
			logger.info("websocket#大屏展示  异常:【{}】",e);
		}
		Tio.sendToUser(channelContext.tioConfig, channelContext.userid, wsResponse);
		return null;
	}


	/**
	 * 给企业发送人员信息
	 */
	public Integer sendToUser(String id,String msg){
		// 给用户发送消息
		WsResponse wsResponse = WsResponse.fromText(msg, "UTF-8");

//		for (Map.Entry entry:clients.entrySet()){
//			System.out.println(entry.getKey());
//			System.out.println(entry.getValue());
//		}

		if(!clients.containsKey(id)){
			return  0;
		}

		TioConfig tioConfig=clients.get(id);

		boolean b= Tio.sendToUser(tioConfig, id, wsResponse);
		return b?1:2;

	}
}
